AVL平衡二叉树C++版

#include <iostream>
using namespace std;

class AVLNode{
public:
	int data;
	int height;//结点的高度,叶子结点高度为1 
	AVLNode* lChild;
	AVLNode* rChild;
public:
	AVLNode(int data):data(data),height(1),lChild(0),rChild(0){} 
};

class AVL{
public:
	AVLNode* root;
public:
	AVL(){
		root = nullptr;
	}
	~AVL(){
		delete root;
	}
	int height(AVLNode* root){
		if(root){
			return root->height;
		}
		return 0;
	} 
	//找到树中最大结点并将其返回 
	AVLNode* finMaxNode(AVLNode* root){
		//一直往右找 
		if(root->rChild){
			root = root->rChild;
		} 
		return root;
	}
	//找到树中最小结点并将其返回 
	AVLNode* finMinNode(AVLNode* root){
		//一直往左找 
		if(root->lChild){
			root = root->lChild;
		} 
		return root;
	}
	//以p为根结点右旋转,返回新的根结点 
	AVLNode* llRotate(AVLNode* p){
		AVLNode* pleft = p->lChild;
		p->lChild = pleft->rChild;
		pleft->rChild = p;	
		//结点的高度由该节点的子树唯一决定,所以只有子树发生变化的结点才需要更新高度值 
		pleft->height = max(height(pleft->lChild), height(pleft->rChild))+1;
		p->height = max(height(p->lChild), height(p->rChild))+1;
		return pleft; 
	}
	//左旋转 
	AVLNode* rrRotate(AVLNode* p){
		AVLNode* pright = p->rChild;
		p->rChild = pright->lChild;
		pright->lChild = p;	
		pright->height = max(height(pright->lChild), height(pright->rChild))+1;
		p->height = max(height(p->lChild), height(p->rChild))+1;
		return pright; 
	}
	//先左,再右 
	AVLNode* lrRotate(AVLNode* p){
		AVLNode* pleft = rrRotate(p->lChild);
		return llRotate(p);
	}
	//先右,再左 
	AVLNode* rlRotate(AVLNode* p){
		AVLNode* pright = llRotate(p->rChild);
		return rrRotate(p);
	}
	//插入新结点,保持平衡 
	void insert(int data, AVLNode*& root){
		if(!root){ 
			root = new AVLNode(data);
		}
		else{
			if(data < root->data){
				insert(data, root->lChild);
				//插入新结点后,如果打破平衡,则需要动态调整 
				if(height(root->lChild)-height(root->rChild) == 2){
					if(data < root->lChild->data)
						root = llRotate(root);
					else
						root = lrRotate(root);
				}
			}
			else if(data > root->data){
				insert(data, root->rChild);
				//插入新结点后,如果打破平衡,则需要动态调整 
				if(height(root->rChild)-height(root->lChild) == 2){
					if(data > root->rChild->data)
						root = rrRotate(root);
					else
						root = rlRotate(root);
				}
			}
			else{
				cout << "AVL中已存在该值:" << data << endl;
			}
		}
		//平衡后,需要更新根结点的高度值
		root->height = max(height(root->lChild), height(root->rChild))+1;
	}
	//删除结点,保持平衡 
	void del(int data, AVLNode*& root){
		if(data < root->data){
			del(data, root->lChild);
			//删除点之后,若AVL树失去平衡,则进行调整
			if(height(root->rChild)-height(root->lChild) == 2){
				AVLNode* r = root->rChild;
				if(height(r->lChild) > height(r->rChild))
					root = rlRotate(root);
				else
					root = rrRotate(root);
			} 
		}
		else if(data > root->data){
			del(data, root->rChild);
			//删除点之后,若AVL树失去平衡,则进行调整
			if(height(root->lChild)-height(root->rChild) == 2){
				AVLNode* l = root->lChild;
				if(height(l->lChild) > height(l->rChild))
					root = llRotate(root);
				else
					root = lrRotate(root);
			}
		}
		else{
			//此时root为要删除的点 
			if(root->lChild && root->rChild){
				if(height(root->lChild) > height(root->rChild)){
					// 如果root的左子树比右子树高;
	                // 则(01)找出root的左子树中的最大节点
	                //   (02)将该最大节点的值赋值给root。
	                //   (03)删除该最大节点。
	                // 这类似于用"root的左子树中最大节点"做"root"的替身;
	                // 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。
					AVLNode* maxNode = finMaxNode(root->lChild);
					root->data = maxNode->data;
					del(maxNode->data, root->lChild);
				}
				else{
					AVLNode* minNode = finMinNode(root->rChild);
					root->data = minNode->data;
					del(minNode->data, root->rChild);
				}
			}
			else{
				if(root->lChild){
					root->data = root->lChild->data;
					root->lChild = nullptr;
				}	
				else if(root->rChild){
					root->data = root->rChild->data;
					root->rChild = nullptr;
				}
				else{
					root = nullptr;//参数是引用,所以此处修改了主函数中的root值 
				}
			}
		}
	}
	void inOrder(AVLNode* root){
		if(root){
			inOrder(root->lChild);
			cout << root->data << endl;
			inOrder(root->rChild);
		}
	}
};

int main(){
	AVL tree;
	tree.insert(5, tree.root);
	tree.insert(15, tree.root);
	tree.insert(25, tree.root);
	tree.insert(35, tree.root);
	tree.insert(45, tree.root);
	tree.insert(55, tree.root);
	tree.del(55, tree.root);
	tree.inOrder(tree.root);
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值